#!/usr/bin/python
# -*- coding: UTF-8 -*-

import json
import random
from enum import Enum

import requests

from enums.sys_type_enum import SysTypeEnum
from utils.commit.oversea_regions import OVERSEA_REGIONS
from utils.commit.submit_wjx_v2 import QuestionareSpider
from utils.common import time_util
from utils.common import uuid_util
from utils.common.init_app import app
from utils.ip_proxy.pinzan_ip_proxy import PinzanHttpProxy
from utils.submit_ua import UserAgentGenerate

session = requests.Session()


class SubmitTypeEnum(Enum):
    """提交类型枚举（通用）"""
    WX = "WX"  # 微信
    PHONE = "PHONE"  # 手机
    PC = "PC"  # 直接提交


def get_ans_sn(url):
    """获取answer_session值"""
    resp = requests.get(url=url)
    answer_session = ''
    for cookie in resp.cookies:
        key = cookie.name
        val = cookie.value
        print(key, val)
        if key == 'answer_session':
            answer_session = val
    return answer_session


class QuestionareSpiderTx(QuestionareSpider):
    def __init__(self, send_title_link, pz_obj, wo_topic_id, sleep_time, area):
        super().__init__(send_title_link, pz_obj, wo_topic_id, sleep_time, area)
        self.sessions = session
        # self.proxy_obj = proxy_obj
        self.pz_obj: PinzanHttpProxy = pz_obj
        self.title_link = send_title_link
        self.wo_topic_id = wo_topic_id
        self.headers = {}
        self.sleep_time = sleep_time or 20  # 问卷需要填写的时间,默认20秒
        self.area = area
        self.ua = UserAgentGenerate.random_phone_micro_messenger()  # 初始化实例默认获取一个ua
        self.can_get_7_code = True
        self.answer_session = get_ans_sn(self.title_link)

    def get_submit_result(self, submitdata, submit_type):
        """
        提交问卷
        :param submitdata: 需要提交数据
        :return:
        """
        # 1. 构建提交参数
        cur_header = dict()
        cur_header['content-type'] = 'application/json; charset=utf-8'
        cur_header['user-agent'] = self.ua  # 模拟微信请求头
        cur_header["Referer"] = self.title_link
        userid = str(uuid_util.uuid4())
        cookie_val = f'answer_session={self.answer_session}; __wj_userid={userid}'
        cur_header['Cookie'] = cookie_val
        # app.logger.debug(f'cur_header={cur_header}')
        uid = submitdata['answer_survey']['uid']
        qst_url_arr = self.title_link.split('/')
        survey_id = int(qst_url_arr[-3])
        hv = qst_url_arr[-2]
        timestamp = time_util.get_time_stamp13_now()
        url = f'https://wj.qq.com/api/v2/respondent/surveys/{survey_id}/answers'
        send_param = f'pv_uid={uid}&hash={hv}&_={timestamp}'
        post_body = submitdata  # build_answer_of_servey(uid, hv, survey_id)
        app.logger.info(f'url={url}')
        app.logger.info(f'send_param={send_param}')
        app.logger.info(f'post_body={json.dumps(post_body)}')
        # 2. 判断ip是否可用
        self.is_ip_available()  # 判断当前ip是否过期，如果过期重新获取一个ip并且立即发送请求
        # 3. 发送请求
        # app.logger.debug(f'area：{self.area}')
        if self.area in OVERSEA_REGIONS:  # 海外发送请求
            # app.logger.debug('发送到海外服务器')
            # 1, 获取海外的代理地址，2，发送到海外服务器
            upper_area = self.area.upper()
            p_url = 'http://cuveecui-' + upper_area + ':yydj8888@proxy.smartproxycn.com:1000'
            oversea_param_dict = dict()
            oversea_param_dict['submit_data'] = post_body #{'submitdata': submitdata}
            oversea_param_dict['request_headers'] = cur_header
            oversea_param_dict['proxy_url'] = p_url
            oversea_send_url = url + '?' + send_param
            oversea_param_dict['url'] = oversea_send_url
            # app.logger.debug('打印请求参数：')
            # app.logger.debug(oversea_param_dict)
            sys_oversea_url = 'http://8.137.54.97:7002/api/overseas/submit'
            oversea_header = dict()
            # oversea_header['content-type'] = 'application/json; charset=UTF-8'
            res = requests.post(url=sys_oversea_url, headers=oversea_header, json=oversea_param_dict, timeout=10)
            oversea_response = res.json()
            if oversea_response and 200 == oversea_response.get('code'):
                pd = oversea_response.get('result')
            else:
                pd = '发送海外数据失败'
        else:  # 默认国内直接发送
            res = requests.post(url=url, headers=cur_header, params=send_param, json=post_body,
                                timeout=10,
                                proxies=self.pz_obj.proxies, allow_redirects=False)
            pd = res.content.decode()
        app.logger.info(f'response_data={pd}')
        return pd

    def submit(self, submitdata):
        """
        提交问卷
        :param submitdata: 需要提交数据
        :return:
        """
        pd = self.get_submit_result(submitdata, SubmitTypeEnum.WX)  # 默认微信提交
        if pd.startswith('10〒'):
            pass
        elif pd.startswith('5〒'):  # 5〒很抱歉，必须微信登录才能填写！
            # 默认就是微信提交，说明此时不应该再用微信提交，则转为使用手机提交
            self.ua = UserAgentGenerate.random_pc()  # 获取pd的ua
            pd = self.get_submit_result(submitdata, SubmitTypeEnum.PHONE)
        elif pd.startswith('7〒'):  # 需要智能验证
            pass
        else:
            pass
        return pd


def convert_data_to_submit_data(db_title_arr, db_res_arr, link) -> str:
    """
    将数据库中的数据转换为需要提交的结果数据
    :param db_title_arr: 题目与数据库结果的映射关系数组
    :param db_res_arr: 需要提交的答案数组
    :param link: 初始URL链接
    :return:
    """
    qst_url_arr = link.split('/')
    survey_id = int(qst_url_arr[-3])
    hv = qst_url_arr[-2]
    sid = str(uuid_util.uuid4())
    uid = str(uuid_util.uuid4())
    res = {"answer_survey": {
            "duration": 75,  # 基础默认值75s，具体会随题目数变化（后面更新）
            "is_update": False,
            "latitude": None,
            "longitude": None,
            "openid": "",
            "pages": [],
            "referrer": "",
            "sid": sid,  # "d934fad0-9058-4a6d-a778-a5e66f529667",
            "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0",
            "uid": uid,  # "48bfcfa7-ffb5-4068-9242-6381228ee97f"
        },
        "hash": hv,  # "ed98"
        "survey_id": survey_id,  # 14048637
    }
    page_list = list()
    page_id_set = set()
    cur_page = None
    dura = 0
    for index in range(len(db_title_arr)):
        dura += random.randint(2, 7)  # 每道题做题时间
        i = db_title_arr[index]
        indexes = i['data_index']
        cur_type = i['sys_type']
        qst_id = i['title_id']
        page_id = i['page_id']
        options = i['options']
        is_new_page = False  # 是否为新页面
        question_list = None
        if page_id in page_id_set:  # 如果已存在则找出对应页面，并将题目列表找出并加入
            is_new_page = False
            tmp_page_list = res['answer_survey']['pages']
            for tmp_page in tmp_page_list:
                if page_id == tmp_page['id']:
                    cur_page = tmp_page
                    question_list = cur_page['questions']
        else:
            page_id_set.add(page_id)
            question_list = list()
            is_new_page = True
        cur_qst = None
        if cur_type == SysTypeEnum.SINGLE.value:  # 单选题
            # 数据格式：{"id":"p-1-abcd","questions":[{"blanks":[],"id":"q-1-abcd","options":[{"checked":1,"id":"o-100-ABCD","text":"单选项1"}],"type":"radio"}}
            cur_value = str(db_res_arr[indexes[0]])
            if '-3' == cur_value:  # -3直接跳过这条数据
                continue
            for option in options:
                if str(option['value']) == cur_value:  # 所有数据转换为字符串进行比较
                    opt_id = option['rl_value']
                    opt_name = option['name']
                    cur_qst = {
                        "blanks": [],
                        "id": qst_id,
                        "options": [
                            {
                                "checked": 1,
                                "id": opt_id,
                                "text": opt_name
                            }
                        ],
                        "type": "radio"
                    }
                    break  # 找到匹配的选项后跳出子循环
        elif cur_type == SysTypeEnum.MULTIPLE.value:  # 多选题
            # 数据格式：{"id":"p-1-abcd","questions":[{"blanks":[],"id":"q-2-zbTg","options":[{"checked":1,"id":"o-3-De0j","text":"多选项3"},{"checked":1,"id":"o-4-H3H5","text":"多选项4"}],"type":"checkbox"}]}
            option_list = list()
            is_jump = False
            for option in options:
                db_value = db_res_arr[option['data_index']]
                if '-3' == db_value:  # -3直接跳过这条数据
                    is_jump = True
                    break
                if '1' != str(db_value):
                    continue
                opt_id = option['rl_value']
                cur_selected_option = {
                    "checked": 1,
                    "id": opt_id,
                    "text": option['name']
                }
                option_list.append(cur_selected_option)
            if is_jump:
                continue
            cur_qst = {
                "blanks": [],
                "id": qst_id,
                "options": option_list,
                "type": "checkbox"
            }
        elif cur_type == SysTypeEnum.SINGLE_SELECT.value:  # 下拉单选题
            # 数据格式：相对单选少了个blanks
            cur_value = str(db_res_arr[indexes[0]])
            if '-3' == cur_value:  # -3直接跳过这条数据
                continue
            for option in options:
                if str(option['value']) == cur_value:  # 所有数据转换为字符串进行比较
                    opt_id = option['rl_value']
                    opt_name = option['name']
                    cur_qst = {
                        "id": qst_id,
                        "options": [
                            {
                                "checked": 1,
                                "id": opt_id,
                                "text": opt_name
                            }
                        ],
                        "type": "select"
                    }
                    break  # 找到匹配的选项后跳出子循环
        elif cur_type == SysTypeEnum.SCALE.value:  # 单选量表题
            # 数据格式：{"id":"p-1-abcd","questions":[{"answer_tags":[],"id":"q-3-HqDe","text":"7","type":"star"}]}
            selected_value = str(db_res_arr[indexes[0]])
            if '-3' == selected_value:  # -3直接跳过这条数据
                continue
            cur_qst = {
                "answer_tags": [],
                "id": qst_id,
                "text": selected_value,
                "type": "star"
            }
        elif cur_type == SysTypeEnum.TEXT.value:  # 填空题
            # 数据格式_日期：{"id":"p-1-abcd","questions":[{"id":"q-12-RinS","text":"2024-01-25T00:00:00.000+08:00","type":"datetime"}]}
            # 数据格式：{"id":"p-1-abcd","questions":[{"id":"q-13-cx4z","text":"填空内容","type":"text"}]}
            filled_value = db_res_arr[indexes[0]]
            if '-3' == filled_value:  # -3直接跳过这条数据
                continue
            title_type = i['title_type']
            s_type = "text"
            if "datetime" == title_type:  # 日期类型
                s_type = "datetime"
            elif 'textarea' == title_type:  # 多行文本
                s_type = 'textarea'
            cur_qst = {
                "id": qst_id,
                "text": filled_value,
                "type": s_type
            }
        elif cur_type == SysTypeEnum.MATRIX.value:  # 单选矩阵题
            # 数据格式：{"id":"p-1-abcd","questions":[{"groups":[{"id":"g-1-ABCD","options":[{"checked":1,"id":"o-1-RuGL","text":"列选项2"}]},{"id":"g-2-EFGH","options":[{"checked":1,"id":"o-3-oCSH","text":"列选项3"}]}],"id":"q-16-lMYv","type":"matrix_radio"}]}
            group_list = list()
            children = i['children']
            counter = 0
            is_jump = False
            for cur_child in children:
                cur_option_list = list()
                options = cur_child['options']
                cur_value = str(db_res_arr[indexes[counter]])
                if '-3' == cur_value:  # -3直接跳过这条数据
                    is_jump = True
                    break
                for option in options:
                    if str(option['value']) == cur_value:
                        cur_option = {
                            "checked": 1,
                            "id": option['rl_value'],
                            "text": option['name']
                        }
                        cur_option_list.append(cur_option)
                cur_group_id = cur_child['rl_value']
                cur_group = {
                    "id": cur_group_id,
                    "options": cur_option_list
                }
                group_list.append(cur_group)
                counter += 1
            if is_jump:
                continue
            cur_qst = {
                "groups": group_list,
                "id": qst_id,
                "type": "matrix_radio"
            }
        elif cur_type == SysTypeEnum.CASCADE_DROPDOWN.value:  # 级联下拉题
            # 数据格式：{"id":"p-1-abcd","questions":[{"id":"q-3-LmN1","type":"chained_selects","id_list":["l-abc1","l-ab12"],"text_list":["选项1","s1子选项2"]}]}
            db_value = db_res_arr[indexes[0]]
            if '-3' == db_value:  # -3直接跳过这条数据
                continue
            id_list = list()
            text_list = list()
            cur_qst = {
                "id": qst_id,
                "type": "chained_selects",
                "id_list": [
                    "l-abc2",
                    "l-ab21"
                ],
                "text_list": [
                    "选项2",
                    "o2子选项1"
                ]
            }
        elif cur_type == SysTypeEnum.SLIDE.value or cur_type == SysTypeEnum.RATE.value:
            pass  # 暂无
        elif cur_type == SysTypeEnum.SORTED.value:  # 排序题
            # 数据格式：{"id":"p-1-abcd","questions":[{"id":"q-8-bGQH","options":[{"id":"o-3-BBqy","sort_no":1},{"id":"o-0-DjiV","sort_no":2},{"id":"o-1-p3hS","sort_no":3}],"type":"sort"}]}
            option_list = list()
            is_jump = False
            for option in options:
                db_value = db_res_arr[option['data_index']]
                if '-3' == db_value:  # -3直接跳过这条数据
                    is_jump = True
                    break
                opt_id = option['rl_value']
                sort_no = db_value
                if -2 == db_value:
                    sort_no = len(options)
                cur_sort_option = {
                    "id": opt_id,
                    "sort_no": sort_no
                }
                option_list.append(cur_sort_option)
            if is_jump:
                continue
            sorted_opt_list = sorted(option_list, key=lambda cur_opt: cur_opt['sort_no'])
            cur_qst = {
                "id": qst_id,
                "options": sorted_opt_list,
                "type": "sort"
            }
        elif cur_type == SysTypeEnum.MULTIPLE_TEXT.value:  # 多项填空
            # 数据格式：{"id":"p-1-abcd","questions":[{"blanks":[{"id":"fillblank-db2a","value":"多项填空"},{"id":"fillblank-820e","value":"23"},{"id":"fillblank-752e","value":"12345678910"}],"id":"q-14-2gun","type":"blanks"}]}
            blank_list = list()
            children = i['children']
            is_jump = False
            for cur_child in children:
                db_value = db_res_arr[cur_child['data_index']]
                if '-3' == db_value:  # -3直接跳过这条数据
                    is_jump = True
                    break
                cur_blank_id = cur_child['rl_value']
                cur_blank = {
                    "id": cur_blank_id,
                    "value": db_value
                }
                blank_list.append(cur_blank)
            if is_jump:
                continue
            cur_qst = {
                "blanks": blank_list,
                "id": qst_id,
                "type": "blanks"
            }
        elif cur_type == SysTypeEnum.MULTIPLE_MATRIX.value:  # 矩阵多选
            # 数据格式：{"id":"p-1-abcd","questions":[{"groups":[{"id":"g-1-ABCD","options":[{"checked":1,"id":"o-1-hgFm","text":"列选项2"}]},{"id":"g-2-EFGH","options":[{"checked":1,"id":"o-3-bW8S","text":"列选项3"}]},{"id":"g-3-0Npm","options":[{"checked":1,"id":"o-4-L3cb","text":"列选项4"}]}],"id":"q-17-8vwD","type":"matrix_checkbox"}]}
            group_list = list()
            children = i['children']
            is_jump = False
            for cur_child in children:
                cur_option_list = list()
                options = cur_child['options']
                for option in options:
                    db_value = str(db_res_arr[option['data_index']])
                    if '-3' == db_value:  # -3直接跳过这条数据
                        is_jump = True
                        break
                    if '1' != db_value:
                        continue
                    cur_option = {
                        "checked": 1,
                        "id": option['rl_value'],
                        "text": option['name']
                    }
                    cur_option_list.append(cur_option)
                if is_jump:
                    break
                cur_group_id = cur_child['rl_value']
                cur_group = {
                    "id": cur_group_id,
                    "options": cur_option_list
                }
                group_list.append(cur_group)
            if is_jump:
                continue
            cur_qst = {
                "groups": group_list,
                "id": qst_id,
                "type": "matrix_checkbox"
            }
        elif cur_type == SysTypeEnum.MATRIX_TEXT.value:  # 矩阵填空
            # 数据格式：{"id":"p-1-abcd","questions":[{"groups":[{"blanks":[{"id":"o-1-abcd","text":"列项1","value":"行1列1"},{"id":"o-2-efgh","text":"列项2","value":"行1列2"},{"id":"o-3-NHOc","text":"列项3","value":"行1列3"}],"id":"g-1-ABCD"},{"blanks":[{"id":"o-1-abcd","text":"列项1","value":"行2列1"},{"id":"o-2-efgh","text":"列项2","value":"行2列2"},{"id":"o-3-NHOc","text":"列项3","value":"行2列3"}],"id":"g-2-EFGH"}],"id":"q-15-kjC5","type":"matrix_blank"}]}
            group_list = list()
            children = i['children']
            is_jump = False
            for cur_child in children:
                cur_blank_list = list()
                options = cur_child['options']
                for option in options:
                    db_value = db_res_arr[option['data_index']]
                    if '-3' == db_value:  # -3直接跳过这条数据
                        is_jump = True
                        break
                    cur_blank = {
                        "id": option['rl_value'],
                        "text": option['name'],  # 列名
                        "value": db_value
                    }
                    cur_blank_list.append(cur_blank)
                if is_jump:
                    break
                cur_group_id = cur_child['rl_value']
                cur_group = {
                    "blanks": cur_blank_list,
                    "id": cur_group_id
                }
                group_list.append(cur_group)
            if is_jump:
                continue
            cur_qst = {
                "groups": group_list,
                "id": qst_id,
                "type": "matrix_blank"
            }
        else:  # 未知
            pass
        question_list.append(cur_qst)
        cur_page = {
            "id": page_id,
            "questions": question_list
        }
        if is_new_page:
            page_list.append(cur_page)
            res['answer_survey']['pages'] = page_list
    # app.logger.debug(f'res={json.dumps(res)}')
    res['answer_survey']['duration'] = dura  # 更新总做题时间
    return res


def do_submit(proxy_region: str, send_title_link: str, submitdata: str, sleep_time: int, wo_topic_id):
    # app.logger.debug(f'do_submit提交数据，wo_topic_id:{wo_topic_id}')
    # 获取品赞代理
    virtual_proxy_area = proxy_region
    if proxy_region in OVERSEA_REGIONS:  # 海外发送请求，默认先使用国内的'全国'请求地址，最后发送的时候改为获取海外的ip
        virtual_proxy_area = 'all'
    pz_obj = PinzanHttpProxy(virtual_proxy_area)
    pz_obj.get_proxy()
    # 创建问卷对象, 发送请求
    qo = QuestionareSpiderTx(send_title_link=send_title_link, pz_obj=pz_obj, wo_topic_id=wo_topic_id,
                           sleep_time=sleep_time, area=proxy_region)
    res = qo.submit(submitdata)  # 提交
    app.logger.debug("Submit_ok!!!")
    return res, pz_obj.host_port_city


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    pass

